/**
 * Copyright (c) 2006-2020, zwl
 * 
 * description  DEBUG用串口设备
 * 
 * Change Logs:
 * Date             Author         Notes
 * 2021-01-27       zwl             创建
 * 
 */
#include "main.h"
#include "EntTypeFramework.h"
#include "debug_uart.h"

extern UART_HandleTypeDef   hlpuart1;

typedef struct{
    /* 发送先进先出队列缓冲区 */
    Fifo_t                  TxFiFo;
    etf_uint8_t             TxBuffer[CONFIG_DEBUG_TX_BUFFER_SIZE];
    /* 接收先进先出队列缓冲区 */
    Fifo_t                  RxFiFo;
    etf_uint8_t             RxBuffer[CONFIG_DEBUG_RX_BUFFER_SIZE];

    UART_HandleTypeDef *    handle;
}debug_user;


static debug_user               debug_user_data;

/* 设备初始化。再打开设备的时候自动执行。参数：设备句柄、打开标志 */
etf_err_t debug_init(etf_device_t dev){
    
    debug_user *                pdevice                 = (debug_user *)(dev->user_data);

    FifoInit( &(pdevice->TxFiFo), pdevice->TxBuffer, CONFIG_DEBUG_TX_BUFFER_SIZE );
    FifoInit( &(pdevice->RxFiFo), pdevice->RxBuffer, CONFIG_DEBUG_RX_BUFFER_SIZE );
    
    pdevice->handle->Instance                           = LPUART1;
    pdevice->handle->Init.BaudRate                      = 115200;
    pdevice->handle->Init.WordLength                    = UART_WORDLENGTH_8B;
    pdevice->handle->Init.StopBits                      = UART_STOPBITS_1;
    pdevice->handle->Init.Parity                        = UART_PARITY_NONE;
    pdevice->handle->Init.Mode                          = UART_MODE_TX_RX;
    pdevice->handle->Init.HwFlowCtl                     = UART_HWCONTROL_NONE;
    pdevice->handle->Init.OneBitSampling                = UART_ONE_BIT_SAMPLE_DISABLE;
    pdevice->handle->AdvancedInit.AdvFeatureInit        = UART_ADVFEATURE_NO_INIT;
                
    if (HAL_UART_Init(pdevice->handle) != HAL_OK){
        Error_Handler();
    }

    return ETF_EOK;
}

/* 打开设备。参数：设备句柄、打开标志 */
etf_err_t debug_open(etf_device_t dev, etf_flag_t flag){

    debug_user *                pdevice                 = (debug_user *)(dev->user_data);
    
    HAL_NVIC_SetPriority( LPUART1_IRQn, 8, 0 );
    HAL_NVIC_EnableIRQ( LPUART1_IRQn );
    
    __HAL_UART_ENABLE_IT(pdevice->handle, UART_IT_RXNE);
    
    return ETF_EOK;
}

/* 关闭设备。参数：设备句柄 */
etf_err_t debug_close(etf_device_t dev){

    debug_user *                pdevice                 = (debug_user *)(dev->user_data);

    HAL_NVIC_DisableIRQ( LPUART1_IRQn );
    __HAL_UART_DISABLE_IT(pdevice->handle, UART_IT_RXNE);
    HAL_UART_MspDeInit(pdevice->handle);
    
    return ETF_EOK;
}

/* 读设备。参数：设备句柄、读设备寄存器地址、数据存放地址、数据尺寸 */
etf_size_t debug_read(etf_device_t dev, etf_off_t pos, void *buffer, etf_size_t size){

    debug_user *                pdevice                 = (debug_user *)(dev->user_data);
    etf_size_t                  i;
    etf_uint8_t *               pbuffer                 = (etf_uint8_t *)buffer;

    for(i = 0; (i < size) && (!IsFifoEmpty( &(pdevice->RxFiFo) )) ; i++){
        pbuffer[i]                                      = FifoPop( &(pdevice->RxFiFo) );
    }
    
    return i;
}

/* 写设备。参数：设备句柄、写设备寄存器地址、数据存放地址、数据尺寸 */
etf_size_t debug_write(etf_device_t dev, etf_off_t pos, const void *buffer, etf_size_t size){

    debug_user *                pdevice                 = (debug_user *)(dev->user_data);
    
    if(HAL_OK == HAL_UART_Transmit(pdevice->handle, (etf_uint8_t *)buffer, size, size*5)){
        return size;
    }
    return 0;
}

/* 控制设备。参数：设备句柄、控制指令、参数 */
etf_err_t debug_control(etf_device_t dev, etf_uint32_t cmd, void *args){
    etf_uint32_t				temp;
    debug_user *				pdevice                 	= (debug_user *)(dev->user_data);

    switch(cmd){
    case    DEBUG_CTRL_CMD_BAUDRATE             :
        temp                                                = (etf_uint32_t)args;
        
        pdevice->handle->Init.BaudRate                      = temp;            
        if (HAL_UART_Init(pdevice->handle) != HAL_OK){
            Error_Handler();
        }
        
    break;

    default :
        return (-ETF_ERROR);
    }
    
    return ETF_EOK;
}

static struct etf_device            debug_device;

static struct etf_device_ops ops                            = {

    .init                                                   = debug_init,
    .open                                                   = debug_open,
    .close                                                  = debug_close,
    .read                                                   = debug_read,
    .write                                                  = debug_write,
    .control                                                = debug_control
};

/**
 *  debug控制台输入输出设备注册
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
etf_err_t debug_bsp_init(void){

    etf_err_t                       res                     = ETF_EOK;

	debug_user_data.handle                                  = &hlpuart1;
	
    debug_device.ops                                        = &ops;
    debug_device.user_data                                  = &debug_user_data;
    debug_device.rx_indicate                                = ETF_NULL;
    debug_device.type                                       = ETF_Device_Class_Char;
    
    res                                                     = etf_device_register(&debug_device, "debug", ETF_DEVICE_FLAG_WRONLY|ETF_DEVICE_FLAG_INT_RX);
    
    return res;
}

/* printf重定向到控制台输入输出设备上 */
int fputc(int ch, FILE *f){
    HAL_UART_Transmit(&hlpuart1, (etf_uint8_t *)&ch, 1, 5);
    return ch;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef * huart){

    etf_uint8_t                     RxChar1;
	if (huart == &hlpuart1) {
        RxChar1                                             = hlpuart1.Instance->RDR;
        FifoPush(&(debug_user_data.RxFiFo), RxChar1);
        if(ETF_NULL != debug_device.rx_indicate){
            debug_device.rx_indicate(&debug_device, 1);
        }
	}

}


/**
  * @brief This function handles USART1 global interrupt.
  */
void LPUART1_IRQHandler(void){
//    etf_uint32_t isrflags                                   = READ_REG(hlpuart1.Instance->SR);
//    etf_uint32_t cr1its                                     = READ_REG(hlpuart1.Instance->CR1);

  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */

	/* UART in mode Transmitter ------------------------------------------------*/
//    if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)){
//        UART_Transmit_IT(&hlpuart1);
//    }
//  
//    /* UART in mode Transmitter end --------------------------------------------*/
//    if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)){
//        UART_EndTransmit_IT(&hlpuart1);
//    }
	
    if(__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) ){
        __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_RXNE);
        HAL_UART_RxCpltCallback(&hlpuart1);
    }
//  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}


